#include <stdio.h>
#include <allegro5/allegro.h>
#include <allegro5/allegro_native_dialog.h>
#include <allegro5/allegro_primitives.h>
#include <allegro5/allegro_font.h>

#include <vector>

#include "Globals.h"
#include "Render.h"
#include "Man.h"
#include "RenderSoil.h"
#include "RenderArrow.h"
#include "Monster.h"

using namespace std;

bool key[] = {false, false, false, false, false};
enum KEYS{ UP, DOWN, LEFT, RIGHT, SPACE};

Man *dig_dug = NULL;
Render *drawDigDug = NULL;
RenderSoil *drawSoil = NULL;
Monster *monster1 = NULL;
Monster *monster2 = NULL;
Render *drawMonster1 = NULL;
Render *drawMonster2 = NULL;
Render *drawInvisible = NULL;
RenderArrow *arrow = NULL;

int main(int argc, char **argv)
{

    const float FPS = 60;

    bool finish = false;
    bool render = false;
    int game_state = PLAYING;


    dig_dug = new Man();

    ALLEGRO_BITMAP *DigDugImage = NULL;
    ALLEGRO_BITMAP *SoilImage = NULL;
    ALLEGRO_BITMAP *MonsterImage = NULL;
    ALLEGRO_BITMAP *ArrowImage = NULL;
    ALLEGRO_BITMAP *YOU_LOOSE = NULL;
    ALLEGRO_BITMAP *YOU_WIN = NULL;
    ALLEGRO_BITMAP *disembodied_monster = NULL;

    vector<vector<bool> > hole_tracker ( 26, vector<bool>(12, false) );
    int hole_tracker_columns = 0;
    int hole_tracker_rows = 0;

    //initialise vector with starting holes

    hole_tracker[3][8] = true;
    hole_tracker[4][8] = true;
    hole_tracker[5][8] = true;
    hole_tracker[6][8] = true;
    hole_tracker[7][8] = true;
    hole_tracker[8][8] = true;

    hole_tracker[17][6] = true;
    hole_tracker[17][7] = true;
    hole_tracker[17][8] = true;
    hole_tracker[17][9] = true;
    hole_tracker[17][10] = true;
    hole_tracker[17][11] = true;

    //monsters vector
    vector< Monster *> all_monsters;

    monster1 = new Monster();
    //all_monsters.push_back(monster1);
    monster2 = new Monster();
    //all_monsters.push_back(monster2);

    //ALLEGRO VARIABLES

    ALLEGRO_DISPLAY *display = NULL;
    ALLEGRO_EVENT_QUEUE *event_queue = NULL;
    ALLEGRO_TIMER *timer = NULL;


    //ALLEGRO INIT + DISPLAY CREATE

    if(!al_init())
    {
        al_show_native_message_box(display, NULL, NULL,
            "failed to initialize allegro!", NULL, NULL);
        return -1;
    }

    display = al_create_display(displayWidth,displayHeight);
    if(!display)
    {
        al_show_native_message_box(display, NULL, NULL,
            "failed to initialize display!", NULL, NULL);
        al_destroy_display(display);
        al_destroy_timer(timer);
        return -1;
    }

    //ADDON

    al_init_primitives_addon();
    al_install_keyboard();
   	al_init_font_addon();


    //PROJECT INIT

    DigDugImage = al_create_bitmap(50, 50);
    if(!DigDugImage)
    {
        al_show_native_message_box(display, NULL, NULL,
            "failed to create bitmap 'DigDugImage'!", NULL, NULL);
        al_destroy_display(display);
        al_destroy_timer(timer);
        return -1;
    }

    //dig dug
    al_set_target_bitmap(DigDugImage);

    al_draw_filled_circle(20,20,18,al_map_rgb(50,50,255));            //head
    al_draw_line(20,36,34,42,al_map_rgb(0,255,255),3);                //leg
    al_draw_line(34,42,38,50,al_map_rgb(0,0,255),3);                //leg
    al_draw_line(38,50,42,49,al_map_rgb(0,0,255),3);                //foot
    al_draw_line(20,36,16,45,al_map_rgb(0,255,255),3);                //leg
    al_draw_line(16,45,10,44,al_map_rgb(0,0,255),3);                //leg
    al_draw_line(10,44,8,48,al_map_rgb(0,0,255),3);                //leg
    al_draw_arc(20,20,9,-0.5,-4,al_map_rgb(255,255,255),22);     //helmet
    al_draw_arc(20,20,12,-0,-0.5,al_map_rgb(200,200,200),23);     //helmet visor
    al_draw_filled_circle(19,19,9,al_map_rgb(165,70,165));
    al_draw_filled_circle(19,19,4,al_map_rgb(255,255,255));
    al_draw_arc(20,20,16,-1,-3,al_map_rgb(150,70,150),2);
    al_draw_filled_circle(30,24,3,al_map_rgb(0,0,0));               //eye
    al_draw_filled_circle(30,24,1,al_map_rgb(200,255,255));               //eyeball
    al_draw_line(20,36,48,36,al_map_rgb(150,150,150),4);
    al_draw_line(29,32,42,32,al_map_rgb(150,150,150),2);
    al_draw_filled_triangle( 46,38,44,38,45,42,al_map_rgb(150,150,150));
    al_draw_filled_triangle( 20,36,36,36,20,42,al_map_rgb(150,150,150));
    al_set_target_backbuffer(display);

    dig_dug -> initialise();
    drawDigDug = new Render(DigDugImage);

    //Soil
    SoilImage = al_create_bitmap( 1300, 600);
    al_set_target_bitmap(SoilImage);
    al_draw_filled_rectangle(0,0, 1300, 150, al_map_rgb(255,255,0));
    al_draw_filled_rectangle(0,150, 1300, 300, al_map_rgb(255,155,0));
    al_draw_filled_rectangle(0,300, 1300, 450, al_map_rgb(255,55,0));
    al_draw_filled_rectangle(0,450, 1300, 600, al_map_rgb(255,0,0));
    drawSoil = new RenderSoil();
    al_set_target_backbuffer(display);


    //Monster
    MonsterImage = al_create_bitmap(50,50);
    al_set_target_bitmap(MonsterImage);
    al_draw_filled_circle(30,30,20,al_map_rgb(255,0,0));
    al_draw_rounded_rectangle(20,20,47,30,3,3,al_map_rgb(255,255,0),4);
    al_draw_line(20,22,10,21,al_map_rgb(255,255,0),4);
    al_draw_filled_rounded_rectangle(21,21,45,28,3,3,al_map_rgb(255,255,255));
    al_draw_filled_rectangle(28,22,30,26,al_map_rgb(0,0,0));
    al_draw_filled_rectangle(37,22,39,26,al_map_rgb(0,0,0));
    al_draw_line(20,49,20,50,al_map_rgb(255,255,0),5);
    al_draw_line(40,49,40,50,al_map_rgb(255,255,0),5);
    al_set_target_backbuffer(display);

    monster1->initialize(150,500);
    monster2->initialize(850,400);

    //all_monsters[0]-> initialize();
    //all_monsters[1]-> initialize();

    drawMonster1 = new Render(MonsterImage);
    drawMonster2 = new Render(MonsterImage);

    //Arrow
    ArrowImage = al_create_bitmap(150, 50);

    arrow = new RenderArrow(ArrowImage);


    //YOU LOOSE
    YOU_LOOSE = al_create_bitmap(750,300);
    al_set_target_bitmap(YOU_LOOSE);

    al_clear_to_color(al_map_rgb(0,0,0));

    al_draw_line(155,5,225,75,al_map_rgb(255,0,0),7);     //y
    al_draw_line(295,5,225,75,al_map_rgb(255,0,0),7);
    al_draw_line(225,75,225,145,al_map_rgb(255,0,0),7);

    al_draw_circle(375,75,70,al_map_rgb(255,0,0),7);       //o

    al_draw_line(455,5,455,145,al_map_rgb(255,0,0),7);     //u
    al_draw_line(455,145,595,145,al_map_rgb(255,0,0),7);
    al_draw_line(595,145,595,5,al_map_rgb(255,0,0),7);

    al_draw_line(15,155,15,295,al_map_rgb(255,0,0),7);      //l
    al_draw_line(15,295,145,295,al_map_rgb(255,0,0),7);

    al_draw_circle(225,225,70,al_map_rgb(255,0,0),7);      //o

    al_draw_circle(375,225,70,al_map_rgb(255,0,0),7);      //o

    al_draw_line(455,155,595,155,al_map_rgb(255,0,0),7);     //s
    al_draw_line(455,155,455,225,al_map_rgb(255,0,0),7);
    al_draw_line(455,225,595,225,al_map_rgb(255,0,0),7);
    al_draw_line(595,225,595,295,al_map_rgb(255,0,0),7);
    al_draw_line(595,295,455,295,al_map_rgb(255,0,0),7);

    al_draw_line(605,155,745,155,al_map_rgb(255,0,0),7);     //e
    al_draw_line(605,155,605,295,al_map_rgb(255,0,0),7);
    al_draw_line(605,225,745,225,al_map_rgb(255,0,0),7);
    al_draw_line(605,295,745,295,al_map_rgb(255,0,0),7);

    al_set_target_backbuffer(display);


    //YOU_WIN
    YOU_WIN = al_create_bitmap(450,300);
    al_set_target_bitmap(YOU_WIN);
    al_clear_to_color(al_map_rgb(0,0,0));

    al_draw_line(5,5,75,75,al_map_rgb(255,0,0),7);     //y
    al_draw_line(145,5,75,75,al_map_rgb(255,0,0),7);
    al_draw_line(75,75,75,145,al_map_rgb(255,0,0),7);

    al_draw_circle(225,75,70,al_map_rgb(255,0,0),7);       //o

    al_draw_line(305,5,305,145,al_map_rgb(255,0,0),7);     //u
    al_draw_line(305,145,445,145,al_map_rgb(255,0,0),7);
    al_draw_line(445,145,445,5,al_map_rgb(255,0,0),7);

    al_draw_line(5,155,50,295,al_map_rgb(255,0,0),7);      //w
    al_draw_line(50,295,75,155,al_map_rgb(255,0,0),7);
    al_draw_line(75,155,100,295,al_map_rgb(255,0,0),7);
    al_draw_line(100,295,145,155,al_map_rgb(255,0,0),7);

    al_draw_line(155,155,295,155,al_map_rgb(255,0,0),7);      //i
    al_draw_line(225,155,225,295,al_map_rgb(255,0,0),7);
    al_draw_line(155,295,295,295,al_map_rgb(255,0,0),7);

    al_draw_line(305,155,305,295,al_map_rgb(255,0,0),7);      //n
    al_draw_line(305,155,445,295,al_map_rgb(255,0,0),7);
    al_draw_line(445,295,445,155,al_map_rgb(255,0,0),7);

    al_set_target_backbuffer(display);

    //disembodied monster
    disembodied_monster = al_create_bitmap(50,50);
    al_set_target_bitmap(disembodied_monster);

    al_draw_rounded_rectangle(20,20,47,30,3,3,al_map_rgb(0,100,255),4);
    al_draw_line(20,22,10,21,al_map_rgb(0,100,255),4);
    al_draw_filled_rounded_rectangle(21,21,45,28,3,3,al_map_rgb(255,255,255));
    al_draw_filled_rectangle(28,22,30,26,al_map_rgb(0,0,0));
    al_draw_filled_rectangle(37,22,39,26,al_map_rgb(0,0,0));
 //   al_draw_line(20,49,20,50,al_map_rgb(255,255,0),5);
 //   al_draw_line(40,49,40,50,al_map_rgb(255,255,0),5);
    al_set_target_backbuffer(display);

    drawInvisible = new Render( disembodied_monster );

    event_queue = al_create_event_queue();
    if(!event_queue)
    {
        al_show_native_message_box(display, NULL, NULL,
            "failed to create even que!", NULL, NULL);
        al_destroy_display(display);
        al_destroy_timer(timer);
        return -1;
    }

    timer = al_create_timer(1.0 / FPS);
    if(!timer)
    {
        al_show_native_message_box(display, NULL, NULL,
            "failed to create timer!", NULL, NULL);
        return -1;
    }

    al_register_event_source(event_queue, al_get_display_event_source(display));
    al_register_event_source(event_queue, al_get_timer_event_source(timer));
    al_register_event_source(event_queue, al_get_keyboard_event_source());

    al_start_timer(timer);

    while (!finish)
    {
        ALLEGRO_EVENT ev;
        al_wait_for_event(event_queue, &ev);

        //INPUTS

        if (ev.type == ALLEGRO_EVENT_KEY_DOWN)
        {
            switch (ev.keyboard.keycode)
            {
                case ALLEGRO_KEY_ESCAPE:
                    finish = true;
                    break;

                case ALLEGRO_KEY_UP:
                    key[UP] = true;
                    break;

                case ALLEGRO_KEY_DOWN:
                    key[DOWN] = true;
                    break;

                case ALLEGRO_KEY_LEFT:
                    key[LEFT] = true;
                    break;

                case ALLEGRO_KEY_RIGHT:
                    key[RIGHT] = true;
                    break;

                case ALLEGRO_KEY_SPACE:
                    key[SPACE] = true;
                    break;

            }
        }
        else if (ev.type == ALLEGRO_EVENT_KEY_UP)
        {
            switch (ev.keyboard.keycode)
            {
                case ALLEGRO_KEY_ESCAPE:
                    finish = true;
                    break;

                case ALLEGRO_KEY_UP:
                    key[UP] = false;
                    break;

                case ALLEGRO_KEY_DOWN:
                    key[DOWN] = false;
                    break;

                case ALLEGRO_KEY_LEFT:
                    key[LEFT] = false;
                    break;

                case ALLEGRO_KEY_RIGHT:
                    key[RIGHT] = false;
                    break;

                case ALLEGRO_KEY_SPACE:
                    key[SPACE] = false;
                    break;

            }
        }

        //UPDATE

        else if (ev.type == ALLEGRO_EVENT_TIMER)
        {

            if(game_state == PLAYING)
            {

                if (key[UP]) dig_dug -> move_up();
                else if (key[DOWN]) dig_dug -> move_down();
                else dig_dug -> still_y();

                if (key[LEFT]) dig_dug -> move_left();
                else if (key[RIGHT]) dig_dug -> move_right();
                else dig_dug -> still_x();

                dig_dug -> update();

                //hole tracking updating
                if (dig_dug->get_pos_x()%50==0 && dig_dug->get_pos_y()%50==0)
                {
                    hole_tracker_columns = dig_dug->get_pos_x()/50;
                    hole_tracker_rows = (dig_dug->get_pos_y()/50) -2;
                    hole_tracker[hole_tracker_columns][hole_tracker_rows] = true;
                }

                monster1 -> position_check();
                monster1 -> check_soil( hole_tracker );
                monster1 -> follow_digdugX( dig_dug );
                monster1 -> follow_digdugY( dig_dug );
                monster1 -> update();

                monster2 -> position_check();
                monster2 -> check_soil( hole_tracker );
                monster2 -> follow_digdugX( dig_dug );
                monster2 -> follow_digdugY( dig_dug );
                monster2 -> update();

                al_set_target_bitmap(SoilImage);
                drawSoil -> updateSoil(dig_dug);


                al_set_target_bitmap(ArrowImage);
                if (key[SPACE]) arrow -> set_expand();
                arrow -> updateArrow();
                al_set_target_backbuffer(display);

                if(dig_dug->collide_monster( monster1->get_xPos(), monster1->get_yPos() ) ||
                   dig_dug->collide_monster( monster2->get_xPos(), monster2->get_yPos() ) )
                {
                    dig_dug -> loose_life();

                    if ( !dig_dug->get_alive() )
                    {
                        game_state = LOOSER;
                    }
                }

                if(monster1->collide_arrow ( arrow->get_arrowHead_posX(), arrow->get_arrowHead_posY()))
                {
                        monster1->set_alive(false);
                }

                if(monster2->collide_arrow ( arrow->get_arrowHead_posX(), arrow->get_arrowHead_posY()))
                {
                        monster2->set_alive(false);
                }
                        //game_state = WINNER;

                if (!monster1->get_alive() && !monster2->get_alive() )
                {
                    game_state = WINNER;
                }

                render = true;
            }

        }

        //RENDER

        if (render && al_is_event_queue_empty(event_queue))
        {

            if (game_state == PLAYING)
            {
                render = false;

                al_draw_bitmap(SoilImage, 0, 100, 0);

                drawDigDug -> drawImage( dig_dug->get_pos_x(), dig_dug->get_pos_y(), dig_dug->get_direction_x(), dig_dug->get_direction_y() );

                if( monster1->getMonster_invisible() )

                    drawInvisible->drawImage(monster1->get_xPos(), monster1->get_yPos(), monster1->get_direction_x(), monster1->get_direction_y());
                else
                    drawMonster1 -> drawImage( monster1->get_xPos(), monster1->get_yPos(), monster1->get_direction_x(), monster1->get_direction_y() );

                if( monster2->getMonster_invisible() )
                    drawInvisible->drawImage(monster2->get_xPos(), monster2->get_yPos(), monster2->get_direction_x(), monster2->get_direction_y());
                else
                    drawMonster2 -> drawImage( monster2->get_xPos(), monster2->get_yPos(), monster2->get_direction_x(), monster2->get_direction_y() );

                arrow -> drawArrowImage(dig_dug);



            }



            if ( game_state == LOOSER )
            {
                al_draw_bitmap(YOU_LOOSE, 200,200,0);
                //finish = true;
            }

            else if ( game_state == WINNER )
            {
                al_draw_bitmap(YOU_WIN, 350,200,0);
                //finish = true;
            }

         //   al_draw_bitmap(disembodied_monster, 300, 0, 0);

            al_flip_display();
            al_clear_to_color(al_map_rgb(0,0,0));

        }

        if (ev.type == ALLEGRO_EVENT_DISPLAY_CLOSE) finish = true;

    }

    //DESTROYS
    al_destroy_bitmap(YOU_LOOSE);
    al_destroy_bitmap(YOU_WIN);
    al_destroy_bitmap(SoilImage);
    arrow -> destroyArrowImage();
    drawDigDug -> destroyImage();
    drawMonster1 -> destroyImage();


    delete drawDigDug;
    delete dig_dug;
    delete drawMonster1;
    delete drawMonster2;
    delete drawInvisible;
    delete monster1;
    delete monster2;
    delete arrow;
    delete drawSoil;

    al_destroy_timer(timer);
    al_destroy_event_queue(event_queue);
    al_destroy_display(display);


   return 0;
}
